package com.atguigu.gmall.secKill.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.model.activity.SeckillGoods;
import com.atguigu.gmall.mq.config.RabbitService;
import com.atguigu.gmall.secKill.mapper.SeckillGoodsMapper;
import com.atguigu.gmall.secKill.mapper.SeckillOrderMapper;
import com.atguigu.gmall.secKill.pojo.SeckillOrder;
import com.atguigu.gmall.secKill.pojo.UserRecode;
import com.atguigu.gmall.secKill.service.SecKillService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @Author ZengMing
 * @Date 2021/7/14 19:28
 * @Description:秒杀接口实现类
 */
@Service
public class SecKillServiceImpl implements SecKillService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RabbitService rabbitService;

    @Autowired
    private SeckillOrderMapper seckillOrderMapper;

    /**
     * 秒杀商品列表
     *
     * @param time
     * @return
     */
    @Override
    public List<SeckillGoods> getSeckillGoods(String time) {
        List<SeckillGoods> seckillGoodsList = redisTemplate.boundHashOps("SeckillGoods_" + time).values();
        return seckillGoodsList;
    }

    /**
     * 秒杀商品详情
     *
     * @param time
     * @param id
     * @return
     */
    @Override
    public SeckillGoods getSeckillGood(String time, String id) {
        SeckillGoods seckillGood = (SeckillGoods) redisTemplate.boundHashOps("SeckillGoods_" + time).get(id);
        return seckillGood;
    }

    /**
     * 用户排队下单
     *
     * @param time
     * @param skuId
     * @param userId
     * @return
     */
    @Override
    public UserRecode addOrder(String time, String skuId, String userId) {
        //记录用户的排队信息
        UserRecode userRecode = new UserRecode();
        //防止用户重复排队(increment相当于i++)
        Long increment = redisTemplate.boundValueOps("SeckillUserQueue_" + userId).increment(1);
        if (increment > 1){
            userRecode.setStatus(3);
            userRecode.setMsg("重复排队!!!");
            return userRecode;
        }
        userRecode.setUsername(userId);
        userRecode.setCreateTime(new Date());
        //状态为排队中(1--排队；2--支付成功；3--支付失败)
        userRecode.setStatus(1);
        userRecode.setGoodsId(skuId);
        userRecode.setTime(time);
        //秒杀数量一般只能一件
        userRecode.setNum(1);
        //将用户的排队信息存入redis中去
        redisTemplate.boundValueOps("SeckillStatus_" + userId).set(userRecode);
        //发送消息进行异步下单
        rabbitService.sendMessage("seckill_exchange",
                "seckill.order.add",
                JSONObject.toJSONString(userRecode));
        //返回用户排队的结果
        return userRecode;
    }

    /**
     * 查询用户的排队信息
     *
     * @param userId
     * @return
     */
    @Override
    public UserRecode getUserRecode(String userId) {
        //直接取之前设置的redis排队信息
        UserRecode userRecode = (UserRecode) redisTemplate.boundValueOps("SeckillStatus_" + userId).get();
        return userRecode;
    }

    /**
     * 查询秒杀订单的详情
     *
     * @param username
     * @param orderId
     * @return
     */
    @Override
    public List<SeckillOrder> getSeckillOrderList(String username, String orderId) {
        //参数校验
        if(StringUtils.isEmpty(orderId)){
            //查询所有秒杀订单的列表
            return redisTemplate.boundHashOps("SeckillOrder_" + username).values();
        }else{
            List<SeckillOrder> seckillOrders = new ArrayList<>();
            //获取指定的秒杀订单详情
            SeckillOrder seckillOrder =
                    (SeckillOrder)redisTemplate.boundHashOps("SeckillOrder_" + username).get(orderId);
            seckillOrders.add(seckillOrder);
            return seckillOrders;
        }
    }

    /**
     * 支付成功
     *
     * @param map
     */
    @Override
    public void paySuccess(Map<String, String> map) {
        //先获取微信的附加参数
        String attach = map.get("attach");
        //若为空则获取支付宝的附加参数
        if(StringUtils.isEmpty(attach)){
            attach = map.get("passback_params");
        }
        //类型转换
        Map<String,String> attachMap = JSONObject.parseObject(attach, Map.class);
        String username = attachMap.get("username");
        String outTradeNo = map.get("out_trade_no");
        //从redis中获取订单的信息
        SeckillOrder seckillOrder =
                (SeckillOrder)redisTemplate.boundHashOps("SeckillOrder_" + username).get(outTradeNo);
        //判断前置状态
        if(seckillOrder != null && seckillOrder.getStatus().equals("0")){
            //修改订单的支付状态
            seckillOrder.setStatus("1");
            seckillOrder.setPayTime(new Date());
            //map获取微信的订单支付单号
            String otn = map.get("transaction_id");
            if(StringUtils.isEmpty(otn)){
                otn = map.get("trade_no");
            }
            seckillOrder.setOutTradeNo(otn);
            //修改redis中订单的状态
            redisTemplate.boundHashOps("SeckillOrder_" + username).put(outTradeNo, seckillOrder);
            //将订单的信息存入数据库
            seckillOrderMapper.insert(seckillOrder);
            //排队标识删除掉
            redisTemplate.delete("SeckillUserQueue_" + username);
            //排队状态可以删掉了
            redisTemplate.delete("SeckillStatus_" + username);
        }
    }

    /**
     * 支付失败
     *
     * @param map
     */
    @Override
    public void payFail(Map<String, String> map) {
        //先获取微信的附加参数
        String attach = map.get("attach");
        //若为空则获取支付宝的附加参数
        if(StringUtils.isEmpty(attach)){
            attach = map.get("passback_params");
        }
        //类型转换
        Map<String,String> attachMap = JSONObject.parseObject(attach, Map.class);
        String username = attachMap.get("username");
        String outTradeNo = map.get("out_trade_no");
        //从redis中获取订单的信息
        SeckillOrder seckillOrder =
                (SeckillOrder)redisTemplate.boundHashOps("SeckillOrder_" + username).get(outTradeNo);
        //判断前置状态
        if(seckillOrder != null && seckillOrder.getStatus().equals("0")){
            //修改订单的支付状态
            seckillOrder.setStatus("2");
            //修改redis中订单的状态
            redisTemplate.boundHashOps("SeckillOrder_" + username).put(outTradeNo, seckillOrder);
            //将订单的信息存入数据库
            seckillOrderMapper.insert(seckillOrder);
            //库存回滚---1.redis回滚  2.数据库回滚
            UserRecode userRecode = (UserRecode)redisTemplate.boundValueOps("SeckillStatus_" + username).get();
            rollBackSeckillGoodsNum(userRecode.getGoodsId(), userRecode.getTime(), userRecode.getNum());
            //排队标识删除掉
            redisTemplate.delete("SeckillUserQueue_" + username);
            //排队状态可以删掉了
            redisTemplate.delete("SeckillStatus_" + username);

        }
    }

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;
    /**
     * 回滚秒杀商品的库存
     */
    private void rollBackSeckillGoodsNum(String skuId, String time, Integer num){
        //从redis中获取商品的数据
        SeckillGoods seckillGoods =
                (SeckillGoods)redisTemplate.boundHashOps("SeckillGoods_" + time).get(skuId);
        if(seckillGoods == null){
            //商品已经售罄了--更新数据库中的库存数据
            seckillGoodsMapper.updateSeckillGoodsStock(skuId, num);
        }else{
            //redis中还有数据--更新redis中的库存数据
            String[] seckillGoodsQueue = getSeckillGoodsQueue(skuId, num);
            redisTemplate.boundListOps("seckillGoodsQueue_" + skuId).leftPushAll(seckillGoodsQueue);
            //回滚库存的对象
            redisTemplate.boundHashOps("SeckillGoodsStockNum").increment(skuId, num);
        }
    }

    /**
     * 构建商品库存个数长度的数组
     * @param goodsId
     * @param stockCount
     * @return
     */
    private String[] getSeckillGoodsQueue(String goodsId, Integer stockCount){
        //构建一个库存长度的数组
        String[] ids = new String[stockCount];
        //元素填充
        for (int i = 0; i < stockCount; i++) {
            ids[i] = goodsId;
        }
        //返回数据
        return ids;
    }
}
